package cn.kingshion.juc.threadAlternate;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 编写一个程序，开启 3 个线程，这三个线程的 ID 分别为 A、B、C，每个线程将自己的 ID 在屏幕上打印 10 遍，
 * 要求输出的结果必须按顺序显示。
 * 如：ABCABCABC…… 依次递归
 */
public class ThreadAlternateTest {
    public static void main(String[] args) {
        ALternateThreadDemo threadDemo = new ALternateThreadDemo();
        /**
         * 新建三个线程
         */
        new Thread(() -> {
            for (int i = 1; i <= 20; i++) {
                threadDemo.loopA(i);
            }
        }, "A").start();

        new Thread(() -> {
            for (int i = 1; i <= 20; i++) {
                threadDemo.loopB(i);
            }
        }, "B").start();

        new Thread(() -> {
            for (int i = 1; i <= 20; i++) {
                threadDemo.loopC(i);
                System.out.println("-------------------------------");
            }
        }, "C").start();
    }

}

class ALternateThreadDemo {
    private int num = 1;
    private Lock lock = new ReentrantLock();
    private Condition cA = lock.newCondition();
    private Condition cB = lock.newCondition();
    private Condition cC = lock.newCondition();

    /**
     * @param totalLoop 第几轮操作数据
     */
    public void loopA(int totalLoop) {
        lock.lock();
        try {
            // 1. 判断
            if (num != 1) {
                cA.await();
            }
            // 2. 操作
            for (int i = 1; i <= 1; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
            }
            // 3. 唤醒
            num = 2;
            cB.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void loopB(int totalLoop) {
        lock.lock();
        try {
            // 1. 判断
            if (num != 2) {
                cB.await();
            }
            // 2. 操作
            for (int i = 1; i <= 1; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
            }
            // 3. 唤醒
            num = 3;
            cC.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void loopC(int totalLoop) {
        lock.lock();
        try {
            // 1. 判断
            if (num != 3) {
                cC.await();
            }
            // 2. 操作
            for (int i = 1; i <= 1; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i + "\t" + totalLoop);
            }
            // 3. 唤醒
            num = 1;
            cA.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}